/* 
 * Charles Douglas
 * CSCE 4230
 */
#include <GL/glut.h>
#include <stdlib.h>

static int shoulder = 0, elbow = 0, xrot = 0, yrot = 0;
static double upper_arm_length = 4.0, lower_arm_length = 3.0;

void init(void) 
{
   glClearColor (0.0, 0.0, 0.0, 0.0);
   glShadeModel (GL_FLAT);
   glEnable(GL_DEPTH_TEST);
}

void display(void)
{
   glLoadIdentity();

   glRotatef ((GLfloat) xrot, 1.0, 0.0, 0.0);
   glRotatef ((GLfloat) yrot, 0.0, 1.0, 0.0);

   glTranslatef (0.0, 0.0, -10.0);

   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glPushMatrix();
      /* translate to shoulder, rotate, translate to center of upper arm */
      glTranslatef ((GLfloat) (-1*upper_arm_length / 2.0), 0.0, 0.0);
      glRotatef ((GLfloat) shoulder, 0.0, 0.0, 1.0);
      glTranslatef ((GLfloat) (upper_arm_length / 2.0), 0.0, 0.0);

      /* draw upper arm*/ 
      glPushMatrix();
         glScalef ((GLfloat) upper_arm_length, 1.0, 1.0);
         glColor3f(1.0, 0, 0);
         glutSolidCube (1.0);
      glPopMatrix();

      /* translate to elbow, rotate, translate to center of lower arm */        
      glTranslatef ((GLfloat) (upper_arm_length / 2.0), 0.0, 0.0);
      glRotatef ((GLfloat) elbow, 0.0, 0.0, 1.0);
      glTranslatef ((GLfloat) (lower_arm_length / 2.0), 0.0, 0.0);

      /* draw lower arm */
      glPushMatrix();
         glScalef ((GLfloat) lower_arm_length, 1.0, 1.0);
         glColor3f(0, 0, 1.0);
         glutSolidCube (1.0);
      glPopMatrix();

   glPopMatrix();
   glutSwapBuffers();
}

void reshape (int w, int h)
{
   glViewport (0, 0, (GLsizei) w, (GLsizei) h); 
   glMatrixMode (GL_PROJECTION);
   glLoadIdentity ();
   gluPerspective(65.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
   glMatrixMode(GL_MODELVIEW);

}

void keyboard (unsigned char key, int x, int y)
{
   switch (key) {
      case 's':
         shoulder = (shoulder + 5) % 360;
         glutPostRedisplay();
         break;
      case 'S':
         shoulder = (shoulder - 5) % 360;
         glutPostRedisplay();
         break;
      case 'e':
         elbow = (elbow + 5) % 360;
         glutPostRedisplay();
         break;
      case 'E':
         elbow = (elbow - 5) % 360;
         glutPostRedisplay();
         break;
      case 'x':
         xrot = (xrot + 5) % 360;
         glutPostRedisplay();
         break;
      case 'X':
         xrot = (xrot - 5) % 360;
         glutPostRedisplay();
         break;
      case 'y':
         yrot = (yrot + 5) % 360;
         glutPostRedisplay();
         break;
      case 'Y':
         yrot = (yrot - 5) % 360;
         glutPostRedisplay();
         break;
      case 27:
         exit(0);
         break;
      default:
         break;
   }
}

void menuResponse(int value)
{
    keyboard(value, 0, 0);
}

int main(int argc, char** argv)
{
   int menu;

   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

   glutInitWindowSize (500, 500); 
   glutInitWindowPosition (100, 100);
   glutCreateWindow (argv[0]);

   menu=glutCreateMenu(menuResponse);
   glutAddMenuEntry("Rotate shoulder forward (s)", 's');
   glutAddMenuEntry("Rotate shoulder backward (S)", 'S');
   glutAddMenuEntry("Rotate elbow forward (e)", 'e');
   glutAddMenuEntry("Rotate elbow backward (E)", 'E');
   glutAddMenuEntry("Rotate about the x-axis forward (e)", 'x');
   glutAddMenuEntry("Rotate about the x-axis backward (E)", 'X');
   glutAddMenuEntry("Rotate about the y-axis forward (e)", 'y');
   glutAddMenuEntry("Rotate about the y-axis backward (E)", 'Y');
   glutAddMenuEntry("Quit (esc)", 27);
   glutAttachMenu(GLUT_RIGHT_BUTTON);

   init ();
   glutDisplayFunc(display); 
   glutReshapeFunc(reshape);
   glutKeyboardFunc(keyboard);
   glutMainLoop();
   return 0;
}
